/*!
 *	Crawl sf people
 */
import java.net.URLEncoder
import groovy.time.TimeCategory
import groovy.json.JsonSlurper
import groovy.util.XmlSlurper
import groovyx.gpars.GParsPool
import sun.misc.BASE64Decoder
import org.jsoup.Jsoup
import org.jsoup.Connection.Method

System.setProperty("http.proxyHost", "proxy.pvgl.sap.corp")
System.setProperty("http.proxyPort", "8080")
System.setProperty("https.proxyHost", "proxy.pvgl.sap.corp")
System.setProperty("https.proxyPort", "8080")

DEFAULT_TIMEOUT = 30000

gradeMap = [
  'Agile Developer': 'T2',
  'Associate Development Architect': 'T3',
  'Associate Support Engineer CoE': 'T1',
  'Developer': 'T2',
  'Developer Associate': 'T1',
  'Development Architect': 'T4',
  'Development Expert': 'T4',
  'Development Manager': 'T4',
  'Development Senior Manager': 'T5',
  'Information Developer': 'T2',
  'Information Developer Associate': 'T1',
  'Knowledge Architect': 'T4',
  'Management Support Specialist': 'T2',
  'Manager AGS': 'T4',
  'N/A': 'N/A',
  'Operations Expert': 'T4',
  'Operations Senior Manager': 'T4',
  'Operations Specialist': 'T2',
  'Product Associate': 'T2',
  'Product Expert': 'T4',
  'Product Specialist': 'T3',
  'Project Consultant - Development': 'T3',
  'Project Expert - Development': 'T4',
  'Project Expert Service &amp; Support': 'T4',
  'Quality Associate': 'T1',
  'Quality Expert': 'T4',
  'Quality Manager IMS': 'T4',
  'Quality Specialist': 'T2',
  'Senior Developer': 'T3',
  'Senior Information Developer': 'T3',
  'Senior Manager AGS': 'T3',
  'Senior Operations Specialist': 'T3',
  'Senior Product Specialist': 'T3',
  'Senior Project Consultant - Development': 'T3',
  'Senior Quality Specialist': 'T3',
  'Senior Solution Specialist': 'T3',
  'Senior Support Engineer CoE': 'T3',
  'Senior Support Engineer MS': 'T3',
  'Senior User Experience Design Specialist': 'T3',
  'Solution Expert': 'T4',
  'Support Architect CoE': 'T4',
  'Support Associate MS': 'T1',
  'Support Engineer ASDS': 'T2',
  'Support Engineer CoE': 'T2',
  'Support Engineer MS': 'T2',
  'Translation Specialist': 'T2',
  'User Experience Design Expert': 'T4',
  'User Experience Design Specialist': 'T2'
]


def login() {
	// parse cookie and saml
	def handshake = new JsonSlurper().parse(new InputStreamReader(System.in))
	def decoder = new BASE64Decoder()
	def cookie = new String(decoder.decodeBuffer(handshake.cookie))
	def html = new String(decoder.decodeBuffer(handshake.html))
	//println cookie
	//println html
	def cookies = [:]
	cookie.split(',').each {
		def cc = it.split(';').first()?.split('=', 2)
		if (cc == null || cc.length < 2 || cc[1] == "") {
			//
		} else {
			//println cc
			cookies.put(cc[0], cc[1])
		}
	}
	//println cookies

	// [GET] IDP
	def doc = Jsoup.parse(html)
	def form = doc.select("#samlResponse")
	def action = form.attr("action")
	def saml = form.select("input[name=SAMLResponse]").val()
	//println action
	//println saml
	//println URLEncoder.encode(saml)
	//println doc

	// [POST] IDP
	println " [POST] IDP..."
	doc = Jsoup.connect(action).timeout(DEFAULT_TIMEOUT).cookies(cookies).data("SAMLResponse", saml).post()
	//println doc
	form = doc.select("form")
	action = form.attr("action")
	saml = form.select("input[name=SAMLResponse]").val()

	// [POST] SP
	println " [POST] SP..."
	def response = Jsoup.connect(action).timeout(DEFAULT_TIMEOUT).data("SAMLResponse", saml).method(Method.POST).followRedirects(false).execute()
	cookies = response.cookies()
	action = response.header('Location')
	def scrb = action.split('=')[1]
	//println action
	//println cookies

	// [GET] SP (check correctness)
	//println "[GET] SP (check correctness)"

	// return session
	return [scrb: scrb, cookies: cookies]
}

def fetchOrg(session) {	
	// 38440 -> Robert Chu
	def action = "https://performancemanager5.successfactors.eu/jsup?m=orgData&nodeid=38440&levels=4&lastparentid=null&lastreportid=null&flat=null&org_ts=1386230656712&_s.crb=${session.scrb}"
	def doc = Jsoup.connect(action).timeout(DEFAULT_TIMEOUT).ignoreContentType(true).cookies(session.cookies).get()
	//def doc = Jsoup.parse(new File("oc.xml"), "utf-8")
	def oc = [:]
	def queue = [doc.select("tree>node").first()] as Queue
	//println queue.getClass().name

	//def count = 100
	while (queue.size()) {
		// pop one
		def node = queue.pop()

		def userid = node.select(">userid").text()	
		def firstname = node.select(">firstname").text()
		def lastname = node.select(">lastname").text()
		
		oc.put(userid, "$firstname $lastname")

		// pushd children
		node.select(">children>node").each {
			queue.push(it)
		}
	}

	//println oc
	return oc
}

def fetchEmp(session, oc) {	

	// for test only
	// oc = oc.take(5)

	// def emp = [:]
	return GParsPool.withPool(24) {
		oc.collectParallel {
			println " retreiving $it"
			def action = "https://performancemanager5.successfactors.eu/xi/ui/edu/pages/prevewProfile.xhtml?selected_user=${it.key}&selected_view=43"
			def doc = Jsoup.connect(action).timeout(DEFAULT_TIMEOUT).cookies(session.cookies).get()
			return [it.key, it.value, doc]
		}
	}.collect {
		def sfid = it[0]
		def name = it[1]
		def doc = it[2]

		def pusers = doc.select("div.pbody.puserinfo>table>tbody")
		def personal = pusers[0]
		def orgnize = pusers[1]
		def network = pusers[2]

		def alias = personal.select(">tr:nth-child(1)>td").text().toLowerCase().trim()
		def fname = personal.select(">tr:nth-child(2)>td").text().trim()
		def lname = personal.select(">tr:nth-child(3)>td").text().trim()
		def title = personal.select(">tr:nth-child(4)>td").text().trim().replace(',', ';')
		def type = personal.select(">tr:nth-child(5)>td").text().trim()
		def email = network.select(">tr:nth-child(1)>td").text().trim()
		def mobile = network.select(">tr:nth-child(3)>td").text().trim()
		def manager = orgnize.select(">tr:nth-child(7)>td").text().trim()

		def grade = gradeMap[type]
	
		return [sfid, fname, lname, name, alias, title, type, grade, email, mobile, manager]
	}
}

def exportCsv(emp) {	
	def csv = "emp.csv"
	new File(csv).withWriter { fs ->
		fs.println "sfid,fname,lname,name,alias,title,type,grade,email,mobile,manager"
		emp.each {
			def cc = ''
			it.each {
				cc += it + ','
			}
			cc.substring(0, cc.size() - 1)
			fs.println cc
		}
	}
	"cmd /c start $csv".execute()
}

def main() {
	println "crawler is working..."

	def session = login()
	println "login successfully, session=$session"

	def oc = fetchOrg(session)
	println "fetch org chart successfully, oc=${oc.size()}"

	def emp = fetchEmp(session, oc)
	println "fech employee details successfully"

	exportCsv(emp)
	println "export employee details to csv successfully"	
}

def main2() {
	def oc = fetchOrg([:])
}

main()
//main2()